﻿package {
	import flash.display.*;
	import flash.geom.ColorTransform;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.events.Event;
	import flash.utils.Timer;

	public class LLK extends Sprite {
		private var llkMC:Sprite;
		private var IconArray:Array;
		private var randomArray:Array;
		private var randomTempArray:Array;
		private var pressArray:Array;
		private var findtoarr:Array;
		private var firsti:Array;
		private var tttArray:Array;
		private var patharray:Array;

		private var arrayChangeStyle:String;
		private var pathcnt:uint;
		private var iconTypes:uint;
		private var xIcons:uint;
		private var yIcons:uint;
		private var totalIcons:uint;
		private var lineWidth:uint;
		private var xLineStart:int;
		private var yLineStart:int;
		private var llkWidth:uint;
		private var timeout:Number;
		private var leftTime:Number;
		private var alpha0flag:uint;
		private var hinti:int;
		private var hintj:int;
		public var enabled:Boolean;
		private var washTimer:Timer;
		private var lineTimer:Timer;

		public function LLK(llkobj:Object,bingo:Function):void {
			arrayChangeStyle=llkobj.changeStyle;
			xIcons=llkobj.xIcons;
			yIcons=llkobj.yIcons;
			iconTypes=llkobj.iconTypes;
			totalIcons=xIcons*yIcons;
			lineWidth=llkobj.lineWidth;
			llkWidth=llkobj.llkWidth;
			xLineStart=(550-(lineWidth-llkWidth)-xIcons*lineWidth)/2;
			yLineStart=(288-(lineWidth-llkWidth)-yIcons*lineWidth)/2.6+80;
			hinti=-1;
			hintj=-1;
			pressArray=new Array("-1","");
			randomArray=SetRandomArray(totalIcons);
			leftTime=0.2;
			lineflag=false;
			enabled=true;

			llkMC=new MovieClip  ;
			addChild(llkMC);
			IconArray=new Array  ;
			SetIcons();
			washTimer=new Timer(20,5);
			washTimer.addEventListener(TimerEvent.TIMER,washTimingHandler);
			washTimer.addEventListener(TimerEvent.TIMER_COMPLETE,washTimerHandler);
			lineTimer=new Timer(leftTime*1000,1);
			lineTimer.addEventListener(TimerEvent.TIMER_COMPLETE,lineTimerHandler);
			this.addEventListener(Game.BINGO.type,bingo);
		}
		private function possible(a:int,b:int):Boolean {
			tttArray=new Array(yIcons+2);
			var i:uint;
			var j:uint;
			for (i=0; i<yIcons+2; i++) {
				tttArray[i]=new Array(xIcons+2);
				for (j=0; j<xIcons+2; j++) {
					if (i==0||i==yIcons+1||j==0||j==xIcons+1) {
						tttArray[i][j]=-1;
					} else {
						if (IconArray[(i-1)*xIcons+j-1].alpha<=.4||IconArray[(i-1)*xIcons+j-1].visible==false) {//已点击，透明度小于0.4，防止浮点数不精确
							tttArray[i][j]=-1;
						} else {
							tttArray[i][j]=IconArray[(i-1)*xIcons+j-1].iconFrame+1;
						}
					}
				}
				//trace("possible,tttArray",tttArray[i]);
			}
			findsteparr=new Array  ;
			findtoarr=new Array  ;
			firsti=new Array  ;
			if (findway(Number(Math.floor(a/xIcons+1)),Number(a%xIcons+1),Number(Math.floor(b/xIcons+1)),Number(b%xIcons+1),0,0,0)) {
				return true;
			} else {
				return false;
			}
		}

		function findway(ax:int,ay:int,bx:int,by:int,to:int,step:int,lev:int):Boolean {//ax，bx表示行，ay，by表示列
			lev++;
			var areturn:Boolean=false;
			var nextstep:int;
			findsteparr[lev]=step;
			findtoarr[lev]=to;
			//trace("findway,a(" + ax + "," + ay + ") b(" + bx + "," + by + ") |" + findtoarr[lev] + "," + findsteparr[lev]);
			if (step==4) {
				//trace("findway,返回1");
				return false;
			}
			var firstto:Array=new Array(4);
			if (ax>bx) {
				firstto[0]=1;
				if (ay>=by) {
					firstto[1]=3,firstto[2]=4;
				}
				if (ay<by) {
					firstto[1]=4,firstto[2]=3;
				}
				firstto[3]=2;
			}
			if (ax<bx) {
				firstto[0]=2;
				if (ay>=by) {
					firstto[1]=3,firstto[2]=4;
				}
				if (ay<by) {
					firstto[1]=4,firstto[2]=3;
				}
				firstto[3]=1;
			}
			if (ax==bx) {
				if (ay>by) {
					firstto[0]=3,firstto[1]=4;
				}
				if (ay<by) {
					firstto[0]=4,firstto[1]=3;
				}
				firstto[2]=1,firstto[3]=2;
			}
			//trace("findway,firstto",firstto);
			var returnflag:Boolean=false;
			if (step==3) {
				switch (to) {
					case 1 :
						if (ax-1==bx&&ay==by) {
							returnflag=true;
						}
						break;
					case 2 :
						if (ax+1==bx&&ay==by) {
							returnflag=true;
						}
						break;
					case 3 :
						if (ax==bx&&ay-1==by) {
							returnflag=true;
						}
						break;
					case 4 :
						if (ax==bx&&ay+1==by) {
							returnflag=true;
						}
				}
			} else if (ax-1==bx&&ay==by||ax+1==bx&&ay==by||ax==bx&&ay-1==by||ax==bx&&ay+1==by) {
				returnflag=true;
			}
			//trace("findway,段2.5");
			if (returnflag==true) {
				patharray[pathcnt]=new Array  ;
				patharray[pathcnt][0]=ax;
				patharray[pathcnt++][1]=ay;
				//trace("findway,返回2");
				return true;
			}
			//trace("findway,段3");
			for (firsti[lev] = 0; firsti[lev] < 4; firsti[lev]++) {;
			//trace("findway,for"+firsti[lev]);
			switch (firstto[firsti[lev]]) {
				case 1 :
					//trace("findway,case1a",ax,ay);
					if (ax>0) {
						//trace("findway,case1b",ax,ay,tttArray[ax-1][ay]);
						if (tttArray[ax-1][ay]<0&&areturn!=1) {
							//trace("findway,case1c",ax,ay);
							if (findtoarr[lev]!=1&&findsteparr[lev]>=0) {
								nextstep=step+1;
							} else {
								nextstep=step;
							}
							if (to!=2) {
								if (findtoarr[lev]==1&&findsteparr[lev]==3) {
									areturn=findway(ax-1,ay,bx,by,1,step,lev);
								} else {
									areturn=findway(ax-1,ay,bx,by,1,nextstep,lev);
								}
							}
						}
					}
					break;
				case 2 :
					//trace("findway,case2a",ax,ay);
					if (ax<yIcons+1) {
						//trace("findway,case2b",ax,ay,tttArray[ax+1][ay]);
						if (tttArray[ax+1][ay]<0&&areturn!=1) {
							//trace("findway,case2c",ax,ay);
							if (findtoarr[lev]!=2&&findsteparr[lev]>=0) {
								nextstep=step+1;
							} else {
								nextstep=step;
							}
							if (to!=1) {
								if (findtoarr[lev]==2&&findsteparr[lev]==3) {
									areturn=findway(ax+1,ay,bx,by,2,step,lev);
								} else {
									areturn=findway(ax+1,ay,bx,by,2,nextstep,lev);
								}
							}
						}
					}
					break;
				case 3 :
					//trace("findway,case3a",ax,ay);
					if (ay>0) {
						//trace("findway,case3b",ax,ay,tttArray[ax][ay-1]);
						if (tttArray[ax][ay-1]<0&&areturn!=1) {
							//trace("findway,case3c",ax,ay);
							if (findtoarr[lev]!=3&&findsteparr[lev]>=0) {
								nextstep=step+1;
							} else {
								nextstep=step;
							}
							if (to!=4) {
								if (findtoarr[lev]==3&&findsteparr[lev]==3) {
									areturn=findway(ax,ay-1,bx,by,3,step,lev);
								} else {
									areturn=findway(ax,ay-1,bx,by,3,nextstep,lev);
								}
							}
						}
					}
					break;
				case 4 :
					//trace("findway,case4a",ax,ay);
					if (ay<xIcons+1) {
						//trace("findway,case4b",ax,ay,tttArray[ax][ay+1]);
						if (tttArray[ax][ay+1]<0&&areturn!=1) {
							//trace("findway,case4c",ax,ay);
							if (findtoarr[lev]!=4&&findsteparr[lev]>=0) {
								nextstep=step+1;
							} else {
								nextstep=step;
							}
							if (to!=3) {
								if (findtoarr[lev]==4&&findsteparr[lev]==3) {
									areturn=findway(ax,ay+1,bx,by,4,step,lev);
								} else {
									areturn=findway(ax,ay+1,bx,by,4,nextstep,lev);
								}
							}
						}
					}
			}
		}
		//trace("findway,段4");
		if (areturn==true) {
			patharray[pathcnt]=new Array  ;
			patharray[pathcnt][0]=ax;
			patharray[pathcnt++][1]=ay;
		}
		//trace("findway,段5");
		//trace("findway,返回3"+areturn);
		return areturn;
	}
	private function llkpress(e:MouseEvent) {
		if (lineTimer.running||! enabled) {
			return;
		}
		var theicon:llkIcon=e.currentTarget;
		var i:int;
		if (pressArray[0]=="-1") {
			pressArray[0]=theicon.iconFrame+1;
			pressArray[1]=theicon.iconid;
			theicon.alpha=.3;
		} else {
			if (pressArray[0]==theicon.iconFrame+1&&pressArray[1]!=theicon.iconid) {
				patharray=new Array  ;
				pathcnt=0;
				if (possible(pressArray[1],theicon.iconid)) {
					theicon.alpha=.3;
					alpha0flag=theicon.iconid;
					theicon.enabled=false;
					randomArray[pressArray[1]]=-1;
					randomArray[theicon.iconid]=-1;
					pressArray[0]="-1";
					IconArray[pressArray[1]].enabled=false;

					//update
					drawline(theicon.iconid);

				} else {
					IconArray[pressArray[1]].alpha=1;
					pressArray[0]="-1";
				}
			} else {
				IconArray[pressArray[1]].alpha=1;
				pressArray[0]="-1";
			}
		}
	}
	public function randomBtnClick(hintflag:Boolean=true):Boolean {
		clearhint();
		if (washTimer.running) {
			return false;
		}
		var i:int;
		washing(true);
		for (i=0; i<200; i++) {//100次防止意外死循环
			if (hintBtnClick(false)) {//存在消除，hintflag=0，不终止洗牌
				break;
			}
			washing(true);
			//trace("randomBtnClick,i",i);
		}
		if (i==100) {//100次也没有洗出能够消除局面，意外输
			this.dispatchEvent(Game.WASH_ERR);
			//trace("randomBtnClick,i",i);
		}
		washTimer.reset();
		washTimer.start();
		//trace("randomBtnClick,i",i);
		return true;

	}
	private function washTimingHandler(event:TimerEvent):void {
		washing(false);
		event.updateAfterEvent();
	}
	private function washTimerHandler(event:TimerEvent):void {
		SetIcons(false);
		washTimer.stop();
	}
	public function washing(realflag:Boolean ):void {
		var tempcntarray=new Array  ;//各个图标的位置
		var tempcnt2array=new Array  ;//各个图标的形状
		var cnt:uint;
		var totalcnt:uint=0;
		for (cnt=0; cnt<totalIcons; cnt++) {
			if (randomArray[cnt]>=0) {
				tempcntarray[totalcnt]=cnt;
				tempcnt2array[totalcnt]=IconArray[cnt].iconFrame;
				totalcnt++;
			}
		}
		//trace("washing,totalcnt",totalcnt);
		//trace("washing,tempcnt2array",tempcnt2array);
		randomTempArray=SetRandomArray(totalcnt);
		var llkx:Number=xLineStart;
		var llky:Number=yLineStart;
		var llki:uint;
		cnt=0;
		for (llki=0; llki<totalIcons; llki++) {
			if (llki%xIcons==0) {
				llkx=xLineStart;
				llky+=lineWidth;
			}
			llkx+=lineWidth;
			if (llki==tempcntarray[cnt]) {
				IconArray[llki].iconFrame=(tempcnt2array[randomTempArray[cnt]]);
				//trace("random",llki,(tempcnt2array[randomTempArray[cnt]]+1));
				if (realflag) {
					//trace("washing,llki",llki);
					randomArray[llki]=tempcnt2array[randomTempArray[cnt]];
				}
				cnt++;
			}
		}
		//trace("washing,totalicons",totalIcons);
		//trace("washing,temparr",randomTempArray);
		//trace("washing,ranarr",randomArray);
	}
	public function hintBtnClick(mark:Boolean):Boolean {
		patharray=new Array  ;
		pathcnt=0;
		for (hinti=0; hinti<totalIcons; hinti++) {
			if (randomArray[hinti]==-1) {
				hinti++;
			}
			for (hintj=hinti+1; hintj<totalIcons; hintj++) {
				if (randomArray[hintj]!=-1&&randomArray[hintj]%iconTypes==randomArray[hinti]%iconTypes) {
					if (possible(hinti,hintj)) {
						if (mark) {
							IconArray[hinti].transform.colorTransform=new ColorTransform(1,1,1,1,90,10,50,0);
							IconArray[hintj].transform.colorTransform=new ColorTransform(1,1,1,1,90,10,50,0);
						}
						return true;
					}
				}
			}
		}
		hinti=-1;
		hintj=-1;
		clearhint();
		return false;
	}
	private function SetIcons(resetflag:Boolean=true):void {
		var llki:uint;
		var llkx:Number=xLineStart;
		var llky:Number=yLineStart;
		for (llki=0; llki<totalIcons; llki++) {
			llkx+=lineWidth;
			if (llki%xIcons==0) {
				llkx=xLineStart;
				if (llki>0) {
					llky+=lineWidth;
				}
			}
			if (IconArray[llki]==null) {
				IconArray[llki]=new llkIcon(llki,randomArray[llki]%iconTypes,llkWidth,llkx,llky,llkpress);
				llkMC.addChild(IconArray[llki]);
			} else {
				if (resetflag) {
					IconArray[llki].resetllkIcon(llki,randomArray[llki]%iconTypes,llkWidth,llkx,llky);
				} else {
					IconArray[llki].iconFrame=randomArray[llki];
				}
			}
		}
	}
	private function SetRandomArray(len:uint):Array {
		//trace("SetRandomArray",len);
		var randomarray=new Array(len);
		var i:uint;
		var temp:int;
		randomarray[0]=Math.floor(Math.random()*len);
		for (i=1; i<len; i++) {
			temp=-1;
			while (temp==-1) {
				temp=Math.floor(Math.random()*len);
				for (var j=0; j<i; j++) {
					if (temp==randomarray[j]) {
						temp=-1;
					}
				}
				if (temp!=-1) {
					randomarray[i]=temp;
				}
			}
		}
		//trace("SetRandomArray",randomarray);
		return randomarray;
	}
	private function arrayChange1():void {//向下
		var i:uint;
		var j:uint;
		for (i=0; i<totalIcons; i++) {
			if (randomArray[i]==-1&&i>=xIcons) {
				j=1;
				while (randomArray[i-xIcons*j]!=-1&&(i-xIcons*j)>=0) {
					randomArray[i-xIcons*(j-1)]=randomArray[i-xIcons*j];
					j++;
				}
				randomArray[i-xIcons*(j-1)]=-1;
			}
		}
	}
	private function arrayChange2():void {//左右分散
		var i:int;
		var j:uint;
		for (i=totalIcons-1; i>=0; i--) {
			if (randomArray[i]==-1&&i%xIcons<(xIcons+1)/2-1) {
				j=1;
				while (randomArray[i+j]!=-1&&(i+j)<=(Math.floor(i/xIcons)*xIcons+Math.floor((xIcons+1)/2)-1)) {
					randomArray[i+(j-1)]=randomArray[i+j];
					j++;
				}
				randomArray[i+(j-1)]=-1;
			}
		}
		for (i=0; i<totalIcons; i++) {
			if (randomArray[i]==-1&&i%xIcons>(xIcons+1)/2) {
				j=1;
				while (randomArray[i-j]!=-1&&(i-j)>=(Math.floor(i/xIcons)*xIcons+Math.floor((xIcons+1)/2))) {
					randomArray[i-(j-1)]=randomArray[i-j];
					j++;
				}
				randomArray[i-(j-1)]=-1;
			}
		}
	}
	private function arrayChange3():void {//左右集中
		var i:int;
		var j:uint;
		for (i=0; i<totalIcons; i++) {
			if (randomArray[i]==-1&&i%xIcons<=(xIcons+1)/2-1&&i%xIcons>0) {
				j=1;
				while (randomArray[i-j]!=-1&&(i-j)>=(Math.floor(i/xIcons)*xIcons)) {
					randomArray[i-(j-1)]=randomArray[i-j];
					j++;
				}
				randomArray[i-(j-1)]=-1;
			}
		}
		for (i=totalIcons-1; i>=0; i--) {
			if (randomArray[i]==-1&&i%xIcons>=Math.floor((xIcons+1)/2)&&i%xIcons<xIcons-1) {
				j=1;
				while (randomArray[i+j]!=-1&&(i+j)<=(Math.floor(i/xIcons)*xIcons+xIcons-1)) {
					randomArray[i+(j-1)]=randomArray[i+j];
					j++;
				}
				randomArray[i+(j-1)]=-1;
			}
		}
	}
	private function arrayChange4():void {//上下分散
		var i:int;
		var j:uint;
		for (i=totalIcons-1; i>=0; i--) {
			if (randomArray[i]==-1&&Math.floor(i/xIcons)<Math.floor((yIcons+1)/2)-1) {
				j=1;
				while (randomArray[i+j*xIcons]!=-1&&(i+j*xIcons)<=(Math.floor((yIcons+1)/2)*xIcons)-1) {
					randomArray[i+(j-1)*xIcons]=randomArray[i+j*xIcons];
					j++;
				}
				randomArray[i+(j-1)*xIcons]=-1;
			}
		}
		for (i=0; i<totalIcons; i++) {
			if (randomArray[i]==-1&&Math.floor(i/xIcons)>Math.floor((yIcons+1)/2)) {
				j=1;
				while (randomArray[i-j*xIcons]!=-1&&(i-j*xIcons)>=(Math.floor((yIcons+1)/2)*xIcons)) {
					randomArray[i-(j-1)*xIcons]=randomArray[i-j*xIcons];
					j++;
				}
				randomArray[i-(j-1)*xIcons]=-1;
			}
		}
	}
	private function arrayChange5():void {//上下集中
		var i:int;
		var j:uint;
		for (i=0; i<totalIcons; i++) {
			if (randomArray[i]==-1&&Math.floor(i/xIcons)<=(Math.floor((yIcons+1)/2)-1)&&Math.floor(i/xIcons)>0) {
				j=1;
				while (randomArray[i-j*xIcons]!=-1&&(i-j*xIcons)>=0) {
					randomArray[i-(j-1)*xIcons]=randomArray[i-j*xIcons];
					j++;
				}
				randomArray[i-(j-1)*xIcons]=-1;
			}
		}
		for (i=totalIcons-1; i>=0; i--) {
			if (randomArray[i]==-1&&Math.floor(i/xIcons)>=Math.floor((yIcons+1)/2)&&Math.floor(i/xIcons)<yIcons-1) {
				j=1;
				while (randomArray[i+j*xIcons]!=-1&&(i+j*xIcons)<=yIcons*xIcons-1) {
					randomArray[i+(j-1)*xIcons]=randomArray[i+j*xIcons];
					j++;
				}
				randomArray[i+(j-1)*xIcons]=-1;
			}
		}
	}
	private function arrayChange(n:String=""):void {
		switch (n) {
			case "Down" :
				arrayChange1();
				break;
			case "LeftRightOut" :
				arrayChange2();
				break;
			case "LeftRightIn" :
				arrayChange3();
				break;
			case "UpDownOut" :
				arrayChange4();
				break;
			case "UpDownIn" :
				arrayChange5();
				break;
			case "4SideOut" ://向外扩散
				arrayChange2();
				arrayChange4();
				break;
			case "4SideIn" ://向内集中
				arrayChange3();
				arrayChange5();
				break;
		}
	}
	private function drawline(iconid):void {
		var i:int;
		var xx:Number;
		var yy:Number;
		llkMC.graphics.lineStyle(2,0xFFD700);
		xx=Number(Math.floor(pressArray[1]%xIcons))*lineWidth+xLineStart+llkWidth/2;
		yy=Number(Math.floor(pressArray[1]/xIcons))*lineWidth+yLineStart+llkWidth/2;
		llkMC.graphics.moveTo(xx,yy);
		for (i=pathcnt-1; i>=0; i--) {
			xx=(patharray[i][1]-1)*lineWidth+xLineStart+llkWidth/2;
			yy=(patharray[i][0]-1)*lineWidth+yLineStart+llkWidth/2;
			llkMC.graphics.lineTo(xx,yy);
		}
		xx=Number(Math.floor(iconid%xIcons))*lineWidth+xLineStart+llkWidth/2;
		yy=Number(Math.floor(iconid/xIcons))*lineWidth+yLineStart+llkWidth/2;
		llkMC.graphics.lineTo(xx,yy);
		//trace("drawline "+patharray,pathcnt-1);
		lineTimer.reset();
		lineTimer.start();
	}
	private function lineTimerHandler(event:TimerEvent):void {
		clearhint();
		llkMC.graphics.clear();
		IconArray[alpha0flag].visible=false;
		IconArray[pressArray[1]].visible=false;
		arrayChange(arrayChangeStyle);
		SetIcons();
		this.dispatchEvent(Game.BINGO);
	}
	private function clearhint():void {
		if (hinti!=-1) {
			IconArray[hinti].transform.colorTransform=new ColorTransform();
		}
		if (hintj!=-1) {
			IconArray[hintj].transform.colorTransform=new ColorTransform();
		}
		hinti=-1;
		hintj=-1;
	}
}
}